package com.benzhitech.core;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

/**
 * 静态资源处理器
 * 负责处理 /static/ 路径下的静态资源请求
 */
public class StaticResourceHandler {

    private static final Logger log = LoggerFactory.getLogger(StaticResourceHandler.class);
    private static final String STATIC_PREFIX = "/static/";
    
    // 常见 MIME 类型映射
    private static final Map<String, String> MIME_TYPES = new HashMap<>();
    
    static {
        // 初始化常见 MIME 类型
        MIME_TYPES.put("html", "text/html");
        MIME_TYPES.put("htm", "text/html");
        MIME_TYPES.put("css", "text/css");
        MIME_TYPES.put("js", "application/javascript");
        MIME_TYPES.put("json", "application/json");
        MIME_TYPES.put("jpg", "image/jpeg");
        MIME_TYPES.put("jpeg", "image/jpeg");
        MIME_TYPES.put("png", "image/png");
        MIME_TYPES.put("gif", "image/gif");
        MIME_TYPES.put("ico", "image/x-icon");
        MIME_TYPES.put("svg", "image/svg+xml");
    }

    /**
     * 判断请求是否为静态资源请求
     */
    public static boolean isStaticResourceRequest(String uri) {
        boolean result = uri != null && uri.startsWith(STATIC_PREFIX);
        log.debug("检查是否为静态资源请求: {} -> {}", uri, result);
        return result;
    }
    
    /**
     * 处理静态资源请求
     */
    public static FullHttpResponse handleRequest(ChannelHandlerContext ctx, FullHttpRequest request) {
        String uri = request.uri();
        log.info("处理静态资源请求: {}", uri);
        
        if (!isStaticResourceRequest(uri)) {
            log.warn("非静态资源请求被传入静态资源处理器: {}", uri);
            return createErrorResponse(HttpResponseStatus.BAD_REQUEST, 
                    "Invalid request for static resource handler");
        }
        
        // 从 URI 中提取资源路径
        String resourcePath = uri.substring(STATIC_PREFIX.length() - 1);
        if (resourcePath.startsWith("/")) {
            resourcePath = resourcePath.substring(1);
        }
        
        // 尝试从类路径加载
        InputStream is = null;
        try {
            // 首先尝试从类加载器加载资源
            ClassLoader classLoader = StaticResourceHandler.class.getClassLoader();
            is = classLoader.getResourceAsStream("static/" + resourcePath);
            
            // 如果类加载器无法加载，尝试从文件系统加载
            if (is == null) {
                // 构建资源的文件系统路径
                // 首先尝试相对路径
                String fsPath = "src/main/resources/static/" + resourcePath;
                File file = new File(fsPath);
                
                // 如果文件不存在，则尝试绝对路径形式
                if (!file.exists()) {
                    log.debug("文件不存在（相对路径）: {}", fsPath);
                    // 获取项目根目录
                    String basePath = System.getProperty("user.dir");
                    fsPath = basePath + "/src/main/resources/static/" + resourcePath;
                    file = new File(fsPath);
                }
                
                if (!file.exists() || !file.isFile()) {
                    log.warn("静态资源不存在 (文件系统): {}", file.getAbsolutePath());
                    return createErrorResponse(HttpResponseStatus.NOT_FOUND, 
                            "Resource not found: " + uri);
                }
                
                log.info("从文件系统加载资源: {}", file.getAbsolutePath());
                is = new FileInputStream(file);
            } else {
                log.info("从类路径加载资源: static/{}", resourcePath);
            }
            
            // 读取资源内容
            byte[] content = readAllBytes(is);
            
            // 获取内容类型
            String contentType = getContentType(resourcePath);
            
            log.info("成功加载静态资源: {}, contentType={}, 大小={}字节", 
                    resourcePath, contentType, content.length);
            
            // 创建响应
            DefaultFullHttpResponse response = new DefaultFullHttpResponse(
                    HttpVersion.HTTP_1_1,
                    HttpResponseStatus.OK,
                    Unpooled.wrappedBuffer(content));
            
            // 设置响应头
            response.headers().set(HttpHeaderNames.CONTENT_TYPE, contentType);
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.length);
            
            return response;
        } catch (IOException e) {
            log.error("读取静态资源时发生异常: {}", resourcePath, e);
            return createErrorResponse(HttpResponseStatus.INTERNAL_SERVER_ERROR, 
                    "Error reading resource: " + e.getMessage());
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    // 忽略关闭异常
                }
            }
        }
    }
    
    /**
     * 根据文件扩展名获取内容类型
     */
    private static String getContentType(String path) {
        String extension = getFileExtension(path);
        String contentType = MIME_TYPES.get(extension.toLowerCase());
        
        if (contentType == null) {
            // 如果无法确定，使用二进制流类型
            contentType = "application/octet-stream";
        }
        
        return contentType;
    }
    
    /**
     * 获取文件扩展名
     */
    private static String getFileExtension(String path) {
        int lastDotIndex = path.lastIndexOf('.');
        if (lastDotIndex > 0) {
            return path.substring(lastDotIndex + 1);
        }
        return "";
    }
    
    /**
     * 读取输入流中的所有字节
     */
    private static byte[] readAllBytes(InputStream is) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(is);
        byte[] buffer = new byte[8192];
        int bytesRead;
        io.netty.buffer.ByteBuf content = io.netty.buffer.Unpooled.buffer();
        
        while ((bytesRead = bis.read(buffer)) != -1) {
            content.writeBytes(buffer, 0, bytesRead);
        }
        
        byte[] bytes = new byte[content.readableBytes()];
        content.readBytes(bytes);
        content.release();
        return bytes;
    }
    
    /**
     * 创建错误响应
     */
    private static FullHttpResponse createErrorResponse(HttpResponseStatus status, String message) {
        DefaultFullHttpResponse response = new DefaultFullHttpResponse(
                HttpVersion.HTTP_1_1,
                status,
                Unpooled.copiedBuffer(message.getBytes()));
        
        response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8");
        response.headers().set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
        
        return response;
    }
} 